﻿using System;
using BoldBrick.Core.Logging;
using BoldBrick.SharePoint.CommonControls.DataObjects.Base;
using Microsoft.SharePoint;

namespace BoldBrick.SharePoint.CommonControls.Extensions
{
	/// <summary>
	/// Extension class for <see cref="SPWeb"/> objects
	/// </summary>
	public static class SPWebEx
	{
		private static readonly ILogger log = Logger.GetLogger(typeof (SPWebEx));

		#region ------ Content Type Extensions ----------------------------------------------------

		/// <summary>
		/// Gets content type of web by content type name
		/// </summary>
		/// <param name="web">Web of the content type</param>
		/// <param name="name">Name of the content type</param>
		/// <returns>Returns content type of the web by content type name if there is one, otherwise returns null.</returns>
		public static SPContentType GetContentType(this SPWeb web, string name)
		{
			try
			{
				SPContentType contentType = web.ContentTypes[name];
				if (contentType == null)
					return null;

				return contentType;
			}
			catch (Exception ex)
			{
				log.Write(LogLevel.Error, ex, "Unable to get '{0}' content type from '{1}' web.", name, web.ServerRelativeUrl);
				return null;
			}
		}

		/// <summary>
		/// Gets content type of web by content type ID
		/// </summary>
		/// <param name="web">Web of the content type</param>
		/// <param name="id">ID of the content type</param>
		/// <returns>Returns content type of the web by content type ID if there is one, otherwise returns null.</returns>
		public static SPContentType GetContentType(this SPWeb web, SPContentTypeId id)
		{
			return GetContentType(web.ContentTypes, id);
		}

		/// <summary>
		/// Gets available content type of web by content type ID
		/// </summary>
		/// <param name="web">Web of the content type</param>
		/// <param name="id">ID of the content type</param>
		/// <returns>Returns available content type of the web by content type ID if there is one, otherwise returns null.</returns>
		public static SPContentType GetAvailableContentType(this SPWeb web, SPContentTypeId id)
		{
			return GetContentType(web.AvailableContentTypes, id);
		}

		/// <summary>
		/// Gets content type in collection by content type ID
		/// </summary>
		/// <param name="contentTypes">Parent collection of the content type</param>
		/// <param name="id">ID of the content type</param>
		/// <returns>Returns content type in collection by content type ID if there is one, otherwise returns null.</returns>
		private static SPContentType GetContentType(SPContentTypeCollection contentTypes, SPContentTypeId id)
		{
			try
			{
				SPContentType contentType = contentTypes[id];
				if (contentType == null)
					return null;


				return contentType;
			}
			catch (Exception ex)
			{
				log.Write(LogLevel.Error, ex, "Unable to get '{0}' content type from collection.", id);
				return null;
			}
		}



		#endregion

		#region ------ List Extenstions -----------------------------------------------------------

		/// <summary>
		/// Creates list based on a template
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="templateName">Name of the template</param>
		/// <param name="listTitle">Title of the list</param>
		/// <param name="listName">Url name of teh list</param>
		/// <param name="desciption">Description of the list</param>
		/// <returns>Returns created list</returns>
		public static SPList CreateList(this SPWeb web, string templateName, string listTitle, string listName, string desciption)
		{
			try
			{
				web.AllowUnsafeUpdates = true;

				SPListTemplate template = web.ListTemplates[templateName];

				// create list with name
				Guid listId = web.Lists.Add(listName, desciption, template);
				SPList list = web.Lists[listId];
				
				// update list title
				list.Title = listTitle;
				list.Update();

				return list;
			}
			catch (Exception ex)
			{
				log.Write(LogLevel.Error, ex, "Unable to create '{0}' list based on '{1}' template in '{2}' web.", listTitle, templateName, web.ServerRelativeUrl);
				return null;
			}
		}

		/// <summary>
		/// Creates list based on a template
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="templateType">Type of the template</param>
		/// <param name="listTitle">Title of the list</param>
		/// <param name="listName">Url name of teh list</param>
		/// <param name="desciption">Description of the list</param>
		/// <returns>Returns created list</returns>
		public static SPList CreateList(this SPWeb web, SPListTemplateType templateType, string listTitle, string listName, string desciption)
		{
			try
			{
				web.AllowUnsafeUpdates = true;

				// create list with name
				Guid listId = web.Lists.Add(listName, desciption, templateType);
				SPList list = web.Lists[listId];
				
				// update list title
				list.Title = listTitle;
				list.Update();

				return list;
			}
			catch (Exception ex)
			{
				log.Write(LogLevel.Error, ex, "Unable to create '{0}' list based on '{1}' template in '{2}' web.", listTitle, templateType, web.ServerRelativeUrl);
				return null;
			}
		}

		/// <summary>
		/// Gets list from web by stored list id in web properties
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="list">List data object</param>
		/// <returns>Returns list from web by stored list id in web properties</returns>
		public static SPList GetList(this SPWeb web, BaseList list)
		{
			string key = GetListIDPropertyKey(web, list);
			
			string listIdValue = web.Properties[key];
			if (string.IsNullOrEmpty(listIdValue))
				return null;
			
			Guid listID = new Guid(listIdValue);
			SPList spList = null;
			try
			{
				spList = web.Lists[listID];
			}
			catch (Exception ex)
			{
				log.Write(LogLevel.Warn, ex, "List with '{0}' ID not found.", listID);
			}
			return spList;
		}

		/// <summary>
		/// Sets list id into web propoerties
		/// </summary>
		/// <param name="web">Parent web of the list</param>
		/// <param name="list">List data object</param>
		/// <param name="listId">List id</param>
		public static void SetListIDProperty(this SPWeb web, BaseList list, Guid listId)
		{
			string key = GetListIDPropertyKey(web, list);
			web.Properties[key] = listId.ToString();
			web.Properties.Update();
		}

		private static string GetListIDPropertyKey(SPWeb web, BaseList list)
		{
			string key = string.Format("ListID_{0}", list.GetListName(web.Language));
			return key;
		}

		#endregion
	}
}
